package service

import (
	"context"
	"fmt"
	"time"

	"gitee.com/wangshh_123/cross-pay-go/src/database"
	"gitee.com/wangshh_123/cross-pay-go/src/models"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// TransactionStatsService 交易统计服务
type TransactionStatsService struct {
	collection *mongo.Collection
}

// NewTransactionStatsService 创建交易统计服务实例
func NewTransactionStatsService() *TransactionStatsService {
	collection := database.GetMongoDBCollection("statistics")
	return &TransactionStatsService{
		collection: collection,
	}
}

// GetTransactionStats 获取交易统计数据
func (s *TransactionStatsService) GetTransactionStats(ctx context.Context, query models.TransactionStatsQuery) (*models.TransactionStatsResponse, error) {
	// 构建查询条件
	filter := bson.M{}

	if query.Month != "" {
		filter["month"] = query.Month
	}

	if query.StartDate != "" && query.EndDate != "" {
		startDate, err := time.Parse("2006-01-02", query.StartDate)
		if err != nil {
			return nil, fmt.Errorf("invalid start_date format: %v", err)
		}

		endDate, err := time.Parse("2006-01-02", query.EndDate)
		if err != nil {
			return nil, fmt.Errorf("invalid end_date format: %v", err)
		}

		filter["created_at"] = bson.M{
			"$gte": startDate,
			"$lte": endDate.Add(24 * time.Hour), // 包含结束日期
		}
	}

	// 设置分页选项
	opts := options.Find()
	if query.Limit > 0 {
		opts.SetLimit(query.Limit)
	}
	if query.Offset > 0 {
		opts.SetSkip(query.Offset)
	}
	opts.SetSort(bson.D{{Key: "created_at", Value: -1}}) // 按创建时间倒序

	// 执行查询
	cursor, err := s.collection.Find(ctx, filter, opts)
	if err != nil {
		return nil, fmt.Errorf("failed to query transaction stats: %v", err)
	}
	defer cursor.Close(ctx)

	// 解析结果
	var stats []models.TransactionStats
	if err := cursor.All(ctx, &stats); err != nil {
		return nil, fmt.Errorf("failed to decode transaction stats: %v", err)
	}

	// 获取总数
	total, err := s.collection.CountDocuments(ctx, filter)
	if err != nil {
		return nil, fmt.Errorf("failed to count transaction stats: %v", err)
	}

	// 计算汇总数据
	summary := s.calculateSummary(stats)

	return &models.TransactionStatsResponse{
		Total:   total,
		Data:    stats,
		Summary: summary,
	}, nil
}

// GetTransactionStatsByMonth 根据月份获取交易统计数据
func (s *TransactionStatsService) GetTransactionStatsByMonth(ctx context.Context, month string) (*models.TransactionStats, error) {
	filter := bson.M{"month": month}

	var stats models.TransactionStats
	err := s.collection.FindOne(ctx, filter).Decode(&stats)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, fmt.Errorf("no transaction stats found for month: %s", month)
		}
		return nil, fmt.Errorf("failed to get transaction stats: %v", err)
	}

	return &stats, nil
}

// GetTransactionStatsByYearMonth 根据年份和月份获取交易统计数据
func (s *TransactionStatsService) GetTransactionStatsByYearMonth(ctx context.Context, year int, month int) (*models.TransactionStats, error) {
	// 构建月份格式：YYYY-MM
	monthStr := fmt.Sprintf("%d-%02d", year, month)
	return s.GetTransactionStatsByMonth(ctx, monthStr)
}

// GetTransactionStatsByMonthNumber 根据月份数字获取交易统计数据（使用当前年份）
func (s *TransactionStatsService) GetTransactionStatsByMonthNumber(ctx context.Context, monthNum int) (*models.TransactionStats, error) {
	currentYear := time.Now().Year()
	return s.GetTransactionStatsByYearMonth(ctx, currentYear, monthNum)
}

// GetDashboardData 获取数据看板数据
func (s *TransactionStatsService) GetDashboardData(ctx context.Context, startDate, endDate string) (*models.DashboardData, error) {
	// 解析日期
	start, err := time.Parse("2006-01-02", startDate)
	if err != nil {
		return nil, fmt.Errorf("invalid start_date format: %v", err)
	}

	end, err := time.Parse("2006-01-02", endDate)
	if err != nil {
		return nil, fmt.Errorf("invalid end_date format: %v", err)
	}

	// 查询指定日期范围内的统计数据
	filter := bson.M{
		"created_at": bson.M{
			"$gte": start,
			"$lte": end.Add(24 * time.Hour),
		},
	}

	cursor, err := s.collection.Find(ctx, filter, options.Find().SetSort(bson.D{{Key: "created_at", Value: 1}}))
	if err != nil {
		return nil, fmt.Errorf("failed to query dashboard data: %v", err)
	}
	defer cursor.Close(ctx)

	var stats []models.TransactionStats
	if err := cursor.All(ctx, &stats); err != nil {
		return nil, fmt.Errorf("failed to decode dashboard data: %v", err)
	}

	// 构建数据看板数据
	dashboard := s.buildDashboardData(stats, start, end)

	return dashboard, nil
}

// calculateSummary 计算汇总数据
func (s *TransactionStatsService) calculateSummary(stats []models.TransactionStats) models.StatisticsData {
	summary := models.StatisticsData{
		CurrencyDistributionUSD: make(map[string]float64),
		CurrencyPercentage:      make(map[string]float64),
		TypeDistribution:        make(map[string]int64),
		TypePercentage:          make(map[string]float64),
		TypeAmountDistribution:  make(map[string]float64),
		TypeAmountPercentage:    make(map[string]float64),
		FeeTypeDistributionUSD:  make(map[string]float64),
		FeeTypePercentage:       make(map[string]float64),
	}

	for _, stat := range stats {
		// 累计基础数据
		summary.TotalTransactions += stat.Statistics.TotalTransactions
		summary.TotalAmountUSD += stat.Statistics.TotalAmountUSD
		summary.TotalFeeDeductionAmount += stat.Statistics.TotalFeeDeductionAmount
		summary.TotalFeeReturnAmount += stat.Statistics.TotalFeeReturnAmount
		summary.TotalRechargeAmountUSD += stat.Statistics.TotalRechargeAmountUSD
		summary.TotalAuthAmountUSD += stat.Statistics.TotalAuthAmountUSD
		summary.NetFundChangeUSD += stat.Statistics.NetFundChangeUSD

		// 累计货币分布
		for currency, amount := range stat.Statistics.CurrencyDistributionUSD {
			summary.CurrencyDistributionUSD[currency] += amount
		}

		// 累计类型分布
		for txnType, count := range stat.Statistics.TypeDistribution {
			summary.TypeDistribution[txnType] += count
		}

		// 累计类型金额分布
		for txnType, amount := range stat.Statistics.TypeAmountDistribution {
			summary.TypeAmountDistribution[txnType] += amount
		}

		// 累计费用类型分布
		for feeType, amount := range stat.Statistics.FeeTypeDistributionUSD {
			summary.FeeTypeDistributionUSD[feeType] += amount
		}
	}

	// 计算百分比
	if summary.TotalAmountUSD > 0 {
		for currency, amount := range summary.CurrencyDistributionUSD {
			summary.CurrencyPercentage[currency] = (amount / summary.TotalAmountUSD) * 100
		}
	}

	if summary.TotalTransactions > 0 {
		for txnType, count := range summary.TypeDistribution {
			summary.TypePercentage[txnType] = (float64(count) / float64(summary.TotalTransactions)) * 100
		}
	}

	if summary.TotalAmountUSD > 0 {
		for txnType, amount := range summary.TypeAmountDistribution {
			summary.TypeAmountPercentage[txnType] = (amount / summary.TotalAmountUSD) * 100
		}
	}

	if summary.TotalFeeDeductionAmount > 0 {
		for feeType, amount := range summary.FeeTypeDistributionUSD {
			summary.FeeTypePercentage[feeType] = (amount / summary.TotalFeeDeductionAmount) * 100
		}
	}

	return summary
}

// buildDashboardData 构建数据看板数据
func (s *TransactionStatsService) buildDashboardData(stats []models.TransactionStats, start, end time.Time) *models.DashboardData {
	dashboard := &models.DashboardData{
		Overview: models.DashboardOverview{},
		Trends: models.DashboardTrends{
			DailyStats:   make([]models.DailyStats, 0),
			MonthlyStats: make([]models.MonthlyStats, 0),
		},
		Distribution: models.DashboardDistribution{
			CurrencyDistribution: make(map[string]float64),
			TypeDistribution:     make(map[string]int64),
			AmountDistribution:   make(map[string]float64),
		},
		Performance: models.DashboardPerformance{},
	}

	// 计算概览数据
	for _, stat := range stats {
		dashboard.Overview.TotalTransactions += stat.Statistics.TotalTransactions
		dashboard.Overview.TotalAmountUSD += stat.Statistics.TotalAmountUSD
		dashboard.Overview.NetFundChangeUSD += stat.Statistics.NetFundChangeUSD
	}

	if dashboard.Overview.TotalTransactions > 0 {
		dashboard.Overview.AverageTransaction = dashboard.Overview.TotalAmountUSD / float64(dashboard.Overview.TotalTransactions)
	}

	// 计算分布数据
	summary := s.calculateSummary(stats)
	dashboard.Distribution.CurrencyDistribution = summary.CurrencyDistributionUSD
	dashboard.Distribution.TypeDistribution = summary.TypeDistribution
	dashboard.Distribution.AmountDistribution = summary.TypeAmountDistribution

	// 计算性能数据（使用最新的统计数据）
	if len(stats) > 0 {
		latest := stats[len(stats)-1].Statistics
		dashboard.Performance.OffHoursPercentage = latest.OffHoursTxnPercentage
		dashboard.Performance.CrossBorderPercentage = latest.CrossBorderTxnPercentage
		dashboard.Performance.HighRiskMCCPercentage = latest.HighRiskMCCTxnPercentage
		dashboard.Performance.RefundVoidPercentage = latest.RefundVoidTxnPercentage
		dashboard.Performance.TransactionAmountCV = latest.TransactionAmountCV
		dashboard.Performance.MaxCardDayTxnCount = latest.MaxCardDayTxnCount
		dashboard.Performance.MaxCardDayTxnAmount = latest.MaxCardDayTxnAmount
	}

	return dashboard
}

// GetLatestTransactionStats 获取最新的交易统计数据
func (s *TransactionStatsService) GetLatestTransactionStats(ctx context.Context) (*models.TransactionStats, error) {
	opts := options.FindOne().SetSort(bson.D{{Key: "created_at", Value: -1}})

	var stats models.TransactionStats
	err := s.collection.FindOne(ctx, bson.M{}, opts).Decode(&stats)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, fmt.Errorf("no transaction stats found")
		}
		return nil, fmt.Errorf("failed to get latest transaction stats: %v", err)
	}

	return &stats, nil
}

// GetTransactionStatsByID 根据ID获取交易统计数据
func (s *TransactionStatsService) GetTransactionStatsByID(ctx context.Context, id string) (*models.TransactionStats, error) {
	objectID, err := primitive.ObjectIDFromHex(id)
	if err != nil {
		return nil, fmt.Errorf("invalid object ID: %v", err)
	}

	filter := bson.M{"_id": objectID}

	var stats models.TransactionStats
	err = s.collection.FindOne(ctx, filter).Decode(&stats)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, fmt.Errorf("transaction stats not found")
		}
		return nil, fmt.Errorf("failed to get transaction stats: %v", err)
	}

	return &stats, nil
}
